package com.swfgui.managers
{
	import com.swfgui.containers.PopUpWindow;
	import com.swfgui.core.Application;
	import com.swfgui.effects.Tween;
	import com.swfgui.events.ResizeEvent;
	import com.swfgui.interfaces.IDisposable;
	import com.swfgui.utils.ArrayUtil;
	import com.swfgui.utils.display.DisplayUtil;
	import com.swfgui.utils.display.Geom;
	import com.swfgui.utils.time.STimer;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Rectangle;

	
	/**
	 * 弹出窗口管理，支持并行排列窗口
	 * @author llj
	 */
	public class PopUpManager
	{	
		//新窗口相对于老窗口的位置
		public static const POSITION_CENTER:int = 0;//直接放在上层
		public static const POSITION_LEFT:int = 1;//位于老窗口的左边
		public static const POSITION_RIGHT:int = 2;	//位于老窗口的右边
		
		/**
		 * 可以并存（同时打开）的窗口
		 * @default 
		 */
		protected static const coexistWindow:Array = [];
		
		protected static var windowList:Array = [];
		protected static var windowListEx:Array = [];
		
		private static var isAddStageEvent:Boolean;
		
		private static var time:STimer;
		
		public function PopUpManager()
		{
			
		}
		
		private static function initStageEvent():void
		{
			if(!isAddStageEvent)
			{
				//Application.instance.addEventListener(ResizeEvent.RESIZE, onStageResize);
				time = new STimer(500, 0, onTimer);
				time.start();
				isAddStageEvent = true;
			}
		}
		
		/**
		 * 防止没有调用removePopUp等
		 */
		private static function onTimer():void
		{
			var num:int = popUpLayer.numChildren;
			for(var i:int = 0; i < num; i++)
			{
				var c:DisplayObject = popUpLayer.getChildAt(i);
				if(c.name == "modalShape" && c is DisplayObjectContainer && 
					(c as DisplayObjectContainer).numChildren == 0)
				{
					popUpLayer.removeChildAt(i);
					i--;
					num--;
				}
			}
		}
		
		/**
		 * 弹出顶级窗口
		 * @param window
		 * @param parent
		 * @param modal
		 * @param position 新窗口相对于老窗口的位置
		 */
		public static function addPopUp(window:DisplayObject, 
			parent:DisplayObjectContainer=null, 
			modal:Boolean = false):void
		{			
			initStageEvent();
			
			//没有老窗口，直接打开
			if(windowList.length == 0)
			{	
				_addPopUp(window, parent, modal);
				return;
			}
			
			var i:int;
			
			//检查有没有打开过这个窗口
			for each(var a:WindowItem in windowList)
			{
				if(window == a.window)
				{
					if(!window.parent)
					{
						windowList.splice(i--, 1);
						removeWindowItem(a);
					}
					else
					{						
						return;
					}
				}
				i++;
			}
			
			var pos:PositionItem;
			var item:WindowItem;
			var item2:WindowItem;
			
			//不可与任何窗口共存，关闭所有老窗口，然后打开
			var coexistWindowList:Array = getCoexistWindow(window);
			if(coexistWindowList.length == 0)
			{
				while(windowList.length > 0)
				{
					item = windowList.pop();
					removeWindowItem(item);
				}
				
				_addPopUp(window, parent, modal);
				return;
			}
			
			var flag:Boolean;
			//关闭不可共存的老窗口
			for(i = 0; i < windowList.length; i++)
			{
				item = windowList[i];				
				flag = false;
				for each(pos in coexistWindowList)
				{
					if(item.window is pos.window1 || item.window is pos.window2)
					{
						flag = true;
					}
				}
				
				if(!flag)
				{
					windowList.splice(i--, 1);
					removeWindowItem(item);
				}
			}
			
			item2 = new WindowItem();
			item2.window = window;
			item2.parent = parent;
			item2.modal = modal;
			addWindowItem(item2);	
			
			var diff:int = 5;
			
			if(windowList.length > 0)
			{
				//新窗口的位置取决于老窗口的位置
				item = windowList[windowList.length - 1];				
				var position:int;
				for each(pos in coexistWindowList)
				{
					if(item.window is pos.window1)
					{
						position = pos.w1w2Position;
					}
					else if(item.window is pos.window2)
					{
						position = pos.w2w1Position;
					}
				}
								
				var centerX:int;
				if(position == POSITION_LEFT)
				{					
					for each(item in windowList)
					{
						centerX = (item.parent.width - item.window.width - window.width) * 0.5 + window.width;
						Tween.to(item.window, 0.5,{x:centerX + diff});						
					}
					Tween.to(window, 0.5, {x:centerX - window.width - diff});
				}
				else if(position == POSITION_RIGHT)
				{
					for each(item in windowList)
					{
						centerX = (item.parent.width - item.window.width - window.width) * 0.5 + item.window.width;
						Tween.to(item.window, 0.5,{x:centerX - item.window.width - diff});						
					}
					Tween.to(window, 0.5, {x:centerX + diff});
				}
			}
			
			windowList.push(item2);
		}
				
		private static function _addPopUp(window:DisplayObject,
										  parent:DisplayObjectContainer,
										  modal:Boolean):void
		{			
			//检查有没有打开过这个窗口
			
			var item:WindowItem = new WindowItem();
			item.window = window;
			item.parent = parent;
			item.modal = modal;
			
			windowList.push(item);
			addWindowItem(item);
		}
				
		public static function onStageResize(event:Event=null):void
		{
			for each(var item:WindowItem in windowList)
			{
				item.updateModalShape();
				item.centerPopUp();
			}
			for each(item in windowListEx)
			{
				item.updateModalShape();
				item.centerPopUp();
			}			
		}
		
		
		/**
		 * 弹出顶级窗口，新老窗口不相互影响
		 * @param window
		 * @param parent
		 * @param modal
		 */
		public static function addPopUpEx(window:DisplayObject, 
										parent:DisplayObjectContainer=null, 
										modal:Boolean = false):void
		{
			initStageEvent();
			
			//检查有没有打开过这个窗口
			var i:int;
			for each(var a:WindowItem in windowListEx)
			{
				if(window == a.window)
				{
					if(!window.parent)
					{
						windowListEx.splice(i--, 1);
						removeWindowItem(a);
					}
					else
					{
						return;
					}
				}
				i++;
			}
			
			var item:WindowItem = new WindowItem();
			item.window = window;
			item.parent = parent;
			item.modal = modal;
			
			windowListEx.push(item);
			addWindowItem(item);
		}
		
		private static function addWindowItem(item:WindowItem):void
		{			
			if(!item.parent)
			{
				item.parent = popUpLayer;
			}
			var window:DisplayObject = item.window;
			item.lastParentWidth = item.parent.width;
			item.lastParentHeight = item.parent.height;
			if(item.modal)
			{
				var spt:Sprite = new Sprite();	
				spt.name = "modalShape";
				item.modalShape = spt;
				item.updateModalShape();
				spt.addChild(window);
				item.parent.addChild(spt);				
			}
			else
			{
				item.parent.addChild(window);
			}
			item.centerPopUp();
			window.alpha = 0;
			Tween.to(window, 0.7, {alpha:1});
			
			//window.addEventListener(Event.REMOVED_FROM_STAGE, onWindowRemoved);
		}
		
		protected static function onWindowRemoved(event:Event):void
		{
			removePopUp(event.currentTarget as DisplayObject);
			removePopUpEx(event.currentTarget as DisplayObject);
		}
		
		private static function removeWindowItem(item:WindowItem):void
		{
			//item.window.removeEventListener(Event.REMOVED_FROM_STAGE, onWindowRemoved);
			if(item.modalShape)
			{
				DisplayUtil.safeRemoveChild(item.modalShape);
			}
			if(item.parent.contains(item.window))
			{
				DisplayUtil.safeRemoveChild(item.window);
			}			
		}
				
		private static function getCoexistWindow(target:DisplayObject):Array
		{
			var rtv:Array = [];
			for each(var a:PositionItem in coexistWindow)
			{
				if(target is a.window1)
				{
					rtv.push(a);
				}
				else if(target is a.window2)
				{
					rtv.push(a);
				}
			}
			
			return rtv;
		}

		public static function centerPopUp(window:DisplayObject, usePx:Boolean=false):void
		{
			if(!window.parent)
			{
				return;
			}
			
			window.x = Math.ceil((window.parent.width - window.width) * 0.5);
			window.y = Math.ceil((window.parent.height - window.height) * 0.5);
			
			if(usePx)
			{
				var rect:Rectangle = Geom.getPxRect(window, window);
				window.x -= rect.x;
				window.y -= rect.y;
			}
		}

		public static function bringToFront(window:DisplayObject):void
		{
			for each(var item:WindowItem in windowList)
			{
				if(item.window == window)
				{
					var obj:DisplayObject = item.modal ? item.modalShape : item.window;
					if(obj.parent)
					{
						obj.parent.setChildIndex(obj, obj.parent.numChildren - 1);
					}
					return;
				}
			}
			
			for each(item in windowListEx)
			{
				if(item.window == window)
				{
					obj = item.modal ? item.modalShape : item.window;
					if(obj.parent)
					{
						obj.parent.setChildIndex(obj, obj.parent.numChildren - 1);
					}
					return;
				}
			}
		}


		public static function removePopUp(window:DisplayObject):void
		{
			if(!window)
			{
				return;
			}
			
			var i:int;
			var len:int = windowList.length;
			for (i = 0; i < len; i++)
			{
				var a:WindowItem = windowList[i];
				if(a.window == window)
				{
					//从列表中删除，删除模态
					windowList.splice(i, 1);
					removeWindowItem(a);
					break;
				}
			}

			/*var item:WindowItem;
			if(windowList.length == 1)
			{
				item = windowList[0];
				
				Tween.to(item.window, 0.5, {x:(item.parent.width - item.window.width) * 0.5, 
					y:(item.parent.height - item.window.height) * 0.5});
			}
			else if(windowList.length > 1)
			{
				item = windowList[0];
				window = item.window;
				var position:int = item.position;
				var wndArr:Array;
				var centerX:int;
				var diff:int = 5;
				
				if(position == POSITION_LEFT)
				{					
					for(i = 1; i < windowList.length; i++)
					{
						wndArr = windowList[i];
						wnd = wndArr[0];
						centerX = (popUpLayerWidth - wnd.width - window.width) * 0.5 + window.width;
						Tween.to(wnd, 0.5,{x:centerX + diff});						
					}
					Tween.to(window, 0.5, {x:centerX - window.width - diff});
				}
				else if(position == POSITION_RIGHT)
				{
					for(i = 1; i < windowList.length; i++)
					{
						wndArr = windowList[i];
						wnd = wndArr[0];
						centerX = (popUpLayerWidth - wnd.width - window.width) * 0.5 + wnd.width;
						Tween.to(wnd, 0.5,{x:centerX - wnd.width - diff});						
					}
					Tween.to(window, 0.5, {x:centerX + diff});
				}
			}*/
		}
		
		/**
		 * 移除窗口，新老窗口不相互影响
		 * @param window
		 */
		public static function removePopUpEx(window:DisplayObject):void
		{
			if(!window)
			{
				return;
			}
				
			var len:int = windowListEx.length;
			var item:WindowItem;
			for (var i:int = 0; i < len; i++)
			{
				item = windowListEx[i];
				if(item.window == window)
				{
					//从列表中删除，删除模态
					windowListEx.splice(i, 1);					
					removeWindowItem(item);	
					break;
				}
			}
		}
		
		/**
		 * 删除所有弹出窗口，并Dispose
		 */
		public static function removeAllPopUp():void
		{
			for each(var item:WindowItem in windowList)
			{
				removeWindowItem(item);
				disposeWindow(item);
			}
			
			for each(item in windowListEx)
			{
				removeWindowItem(item);				
				disposeWindow(item);
			}
			
			windowList.length = 0;
			windowListEx.length = 0;			
		}
		
		private static function disposeWindow(item:WindowItem):void
		{
			if(item.window is PopUpWindow)
			{
				(item.window as PopUpWindow).hide();
			}
			else
			{
				if(item.window is IDisposable)
				{
					(item.window as IDisposable).dispose();
				}
			}
		}
		
		/**
		 * 设置窗口共存模式
		 * @param window1 窗口1 Class
		 * @param window2 窗口2 Class
		 * @param w1w2Position w1先打开，w2后打开，w2相对于w1的位置
		 * @param w2w1Position w2先打开，w1后打开，w1相对于w2的位置
		 */
		public static function addCoexistWindow(window1:Class, window2:Class, w1w2Position:int=2, w2w1Position:int=1):void
		{
			for each(var item:PositionItem in coexistWindow)
			{
				if(item.window1 == window1 && item.window2 == window2)
				{
					item.w1w2Position = w1w2Position;
					item.w2w1Position = w2w1Position;
					return;
				}
			}
			
			item = new PositionItem();
			item.window1 = window1;
			item.window2 = window2;
			item.w1w2Position = w1w2Position;
			item.w2w1Position = w2w1Position;
			
		}

		public static function get popUpLayer():DisplayObjectContainer
		{
			return Application.instance.popUpLayer;
		}
	}
}
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;

class WindowItem
{
	public function WindowItem()
	{
		
	}
	
	public var window:DisplayObject;
	public var modal:Boolean;
	public var position:int;
	public var parent:DisplayObjectContainer;
	public var modalShape:Sprite;
	
	public var lastParentWidth:Number;
	public var lastParentHeight:Number;
		
	public function updateModalShape():void
	{
		if(!parent || !modalShape)
		{
			return;
		}
				
		modalShape.graphics.clear();
		modalShape.graphics.beginFill(0, 0);
		modalShape.graphics.drawRect(0,0,parent.width, parent.height);
		modalShape.graphics.endFill();
	}
	
	public function centerPopUp():void
	{
		window.x = Math.ceil((parent.width - window.width) * 0.5);
		window.y = Math.ceil((parent.height - window.height) * 0.5);
	}
	
	public function onParentResize():void
	{
		var dx:Number = (parent.width - lastParentWidth) * 0.5;
		var dy:Number = (parent.height - lastParentHeight) * 0.5;
		lastParentWidth = parent.width;
		lastParentHeight = parent.height;
		
		window.x += dx;
		window.y += dy;
	}
}

class PositionItem
{
	public function PositionItem()
	{
		
	}
	
	public var window1:Class;
	public var window2:Class;
	public var w1w2Position:int;
	public var w2w1Position:int;
}